package org.dce.screencapturer.objects;

import java.awt.AWTEvent;
import java.awt.Color;
import java.awt.Container;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JComponent;

@SuppressWarnings("serial")
public class Dot extends JComponent {
	
	private Point dragPoint; 
	private boolean allowMoveInX;
	private boolean allowMoveInY;
	private boolean allowMoveOutsideX;
	private boolean allowMoveOutsideY;
	private List<DotListener> listeners = new ArrayList<DotListener>();

	public Dot(){
		this(true,true);
	}

	public Dot(boolean allowMoveInX, boolean allowMoveInY){
		this(allowMoveInX,allowMoveInY,false,false);
	}
	public Dot(
			boolean allowMoveInX,
			boolean allowMoveInY,
			boolean allowMoveOutsideX,
			boolean allowMoveOutsideY){
		setLocation(10,10);
		setSize(9,9);
		setFocusable(false);
		enableEvents(AWTEvent.MOUSE_EVENT_MASK|AWTEvent.MOUSE_MOTION_EVENT_MASK);
		this.allowMoveInX = allowMoveInX;
		this.allowMoveInY = allowMoveInY;
		this.allowMoveOutsideX = allowMoveOutsideX;
		this.allowMoveOutsideY = allowMoveOutsideY;
	}
	
	public void addDotListener(DotListener listener){
		listeners.add(listener);
	}
	
	public void removeDotListener(DotListener listener){
		listeners.remove(listener);
	}

	public int getLeftX() {
		return getX()+getWidth();
	}

	public int getBottomY() {
		return getY()+getHeight();
	}

	protected void notifyDragStarted(){
		DotEvent event = new DotEvent(this);
		for (DotListener listener:new ArrayList<DotListener>(listeners)){
			listener.dragStarted(event);
		}
	}
	
	protected void notifyDragFinished(){
		DotEvent event = new DotEvent(this);
		for (DotListener listener:new ArrayList<DotListener>(listeners)){
			listener.dragFinished(event);
		}
	}
	
	public int getCenterX(){
		return getX()+getWidth()/2;
	}
	
	public int getCenterY(){
		return getY()+getHeight()/2;
	}
	
	public Point getCenter(){
		return new Point(getX()+getWidth()/2,getY()+getHeight()/2);
	}
	
	public void setLocationFromBottomRight(Point point){
		setLocation(point.x-getWidth(),point.y-getHeight());
	}
	public void setLocationFromCenter(Point point){
		setLocationFromCenter(point.x,point.y);
	}
	public void setLocationFromCenter(int x, int y){
		setLocation(x-getWidth()/2,y-getHeight()/2);
	}
	
	protected void paintComponent(Graphics g){
		g.setColor(Color.WHITE);
		g.fillOval(0,0,getWidth()-1,getHeight()-1);
		g.setColor(Color.BLACK);
		g.drawOval(0,0,getWidth()-1,getHeight()-1);
	}
	
	protected void processMouseEvent(MouseEvent event){
		switch (event.getID()){
		case MouseEvent.MOUSE_PRESSED:
			dragPoint = event.getPoint();
			notifyDragStarted();
			break;
		case MouseEvent.MOUSE_RELEASED:
			dragPoint = null;
			notifyDragFinished();
			break;
		}
		super.processMouseEvent(event);
	}
	
	protected void processMouseMotionEvent(MouseEvent event){
		if (event.getID() == MouseEvent.MOUSE_DRAGGED){
			
			Container parent = getParent();
			
			int maxX = parent.getWidth()-9;
			int maxY = parent.getHeight()-9;

			int x;
			
			if (allowMoveInX){
				x = getX()+event.getX()-dragPoint.x;
				
				if (!allowMoveOutsideX){
					if (x < 0){
						x = 0;
					} else if (x > maxX){
						x = maxX;
					}
				}
				
			} else {
				x = getX();
			}
			
			int y;
			if (allowMoveInY){
				y = getY()+event.getY()-dragPoint.y;
				
				if (!allowMoveOutsideY){
					if (y < 0){
						y = 0;
					} else if (y > maxY){
						y = maxY;
					}
				}
				
			} else {
				y = getY();
			}
			
			setLocation(x,y);
		}
		super.processMouseMotionEvent(event);
	}
	
}